home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / sptmbr16.lha / fin.lisp < prev    next >
Text File  |  1992-12-21  |  69KB  |  1,963 lines

  1. ;;;-*-Mode:LISP; Package:(PCL Lisp 1000); Base:10; Syntax:Common-lisp -*-
  2. ;;;
  3. ;;; *************************************************************************
  4. ;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
  5. ;;; All rights reserved.
  6. ;;;
  7. ;;; Use and copying of this software and preparation of derivative works
  8. ;;; based upon this software are permitted.  Any distribution of this
  9. ;;; software or derivative works must comply with all applicable United
  10. ;;; States export control laws.
  11. ;;; 
  12. ;;; This software is made available AS IS, and Xerox Corporation makes no
  13. ;;; warranty about the software, its performance or its conformity to any
  14. ;;; specification.
  15. ;;; 
  16. ;;; Any person obtaining a copy of this software is requested to send their
  17. ;;; name and post office or electronic mail address to:
  18. ;;;   CommonLoops Coordinator
  19. ;;;   Xerox PARC
  20. ;;;   3333 Coyote Hill Rd.
  21. ;;;   Palo Alto, CA 94304
  22. ;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
  23. ;;;
  24. ;;; Suggestions, comments and requests for improvements are also welcome.
  25. ;;; *************************************************************************
  26. ;;;
  27.  
  28.   ;;   
  29. ;;;;;; FUNCALLABLE INSTANCES
  30.   ;;
  31.  
  32. #|
  33.  
  34. Generic functions are instances with meta class funcallable-standard-class.
  35. Instances with this meta class are called funcallable-instances (FINs for
  36. short).  They behave something like lexical closures in that they have data
  37. associated with them (which is used to store the slots) and are funcallable.
  38. When a funcallable instance is funcalled, the function that is invoked is
  39. called the funcallable-instance-function.  The funcallable-instance-function
  40. of a funcallable instance can be changed.
  41.  
  42. This file implements low level code for manipulating funcallable instances.
  43.  
  44. It is possible to implement funcallable instances in pure Common Lisp.  A
  45. simple implementation which uses lexical closures as the instances and a
  46. hash table to record that the lexical closures are funcallable instances
  47. is easy to write.  Unfortunately, this implementation adds significant
  48. overhead:
  49.  
  50.    to generic-function-invocation (1 function call)
  51.    to slot-access (1 function call or one hash table lookup)
  52.    to class-of a generic-function (1 hash-table lookup)
  53.  
  54. In addition, it would prevent the funcallable instances from being garbage
  55. collected.  In short, the pure Common Lisp implementation really isn't
  56. practical.
  57.  
  58. Instead, PCL uses a specially tailored implementation for each Common Lisp and
  59. makes no attempt to provide a purely portable implementation.  The specially
  60. tailored implementations are based on the lexical closure's provided by that
  61. implementation and are fairly short and easy to write.
  62.  
  63. Some of the implementation dependent code in this file was originally written
  64. by someone in the employ of the vendor of that Common Lisp.  That code is
  65. explicitly marked saying who wrote it.
  66.  
  67. |#
  68.  
  69. (in-package :pcl)
  70.  
  71. ;;;
  72. ;;; The first part of the file contains the implementation dependent code to
  73. ;;; implement funcallable instances.  Each implementation must provide the
  74. ;;; following functions and macros:
  75. ;;; 
  76. ;;;    ALLOCATE-FUNCALLABLE-INSTANCE-1 ()
  77. ;;;       should create and return a new funcallable instance.  The
  78. ;;;       funcallable-instance-data slots must be initialized to NIL.
  79. ;;;       This is called by allocate-funcallable-instance and by the
  80. ;;;       bootstrapping code.
  81. ;;;
  82. ;;;    FUNCALLABLE-INSTANCE-P (x)
  83. ;;;       the obvious predicate.  This should be an INLINE function.
  84. ;;;       it must be funcallable, but it would be nice if it compiled
  85. ;;;       open.
  86. ;;;
  87. ;;;    SET-FUNCALLABLE-INSTANCE-FUNCTION (fin new-value)
  88. ;;;       change the fin so that when it is funcalled, the new-value
  89. ;;;       function is called.  Note that it is legal for new-value
  90. ;;;       to be copied before it is installed in the fin, specifically
  91. ;;;       there is no accessor for a FIN's function so this function
  92. ;;;       does not have to preserve the actual new value.  The new-value
  93. ;;;       argument can be any funcallable thing, a closure, lambda
  94. ;;;       compiled code etc.  This function must coerce those values
  95. ;;;       if necessary.
  96. ;;;       NOTE: new-value is almost always a compiled closure.  This
  97. ;;;             is the important case to optimize.
  98. ;;;
  99. ;;;    FUNCALLABLE-INSTANCE-DATA-1 (fin data-name)
  100. ;;;       should return the value of the data named data-name in the fin.
  101. ;;;       data-name is one of the symbols in the list which is the value
  102. ;;;       of funcallable-instance-data.  Since data-name is almost always
  103. ;;;       a quoted symbol and funcallable-instance-data is a constant, it
  104. ;;;       is possible (and worthwhile) to optimize the computation of
  105. ;;;       data-name's offset in the data part of the fin.
  106. ;;;       This must be SETF'able.
  107. ;;;       
  108.  
  109. (eval-when (compile load eval)
  110. (defconstant funcallable-instance-data
  111.              '(wrapper slots)
  112.   "These are the 'data-slots' which funcallable instances have so that
  113.    the meta-class funcallable-standard-class can store class, and static
  114.    slots in them.")
  115. )
  116.  
  117. (defmacro funcallable-instance-data-position (data)
  118.   (if (and (consp data)
  119.            (eq (car data) 'quote))
  120.       (or (position (cadr data) funcallable-instance-data :test #'eq)
  121.           (progn
  122.             (warn "Unknown funcallable-instance data: ~S." (cadr data))
  123.             `(error "Unknown funcallable-instance data: ~S." ',(cadr data))))
  124.       `(position ,data funcallable-instance-data :test #'eq)))
  125.  
  126. (proclaim '(notinline called-fin-without-function))
  127. (defun called-fin-without-function (&rest args)
  128.   (declare (ignore args))
  129.   (error "Attempt to funcall a funcallable-instance without first~%~
  130.           setting its funcallable-instance-function."))
  131.  
  132.  
  133. ;;;
  134. ;;; In Lucid Lisp, compiled functions and compiled closures have the same
  135. ;;; representation.  They are called procedures.  A procedure is a basically
  136. ;;; just a constants vector, with one slot which points to the CODE.  This
  137. ;;; means that constants and closure variables are intermixed in the procedure
  138. ;;; vector.
  139. ;;;
  140. ;;; This code was largely written by JonL@Lucid.com.  Problems with it should
  141. ;;; be referred to him.
  142. ;;; 
  143. #+Lucid
  144. (progn
  145.  
  146. (defconstant procedure-is-funcallable-instance-bit-position 10)
  147.  
  148. (defconstant fin-trampoline-fun-index lucid::procedure-literals)
  149.  
  150. (defconstant fin-size (+ fin-trampoline-fun-index
  151.              (length funcallable-instance-data)
  152.              1))
  153.  
  154. ;;;
  155. ;;; The inner closure of this function will have its code vector replaced
  156. ;;;  by a hand-coded fast jump to the function that is stored in the 
  157. ;;;  captured-lexical variable.  In effect, that code is a hand-
  158. ;;;  optimized version of the code for this inner closure function.
  159. ;;;
  160. (defun make-trampoline (function)
  161.   (declare (optimize (speed 3) (safety 0)))
  162.   #'(lambda (&rest args)
  163.       (apply function args)))
  164.  
  165. (eval-when (eval) 
  166.   (compile 'make-trampoline)
  167.   )
  168.  
  169.  
  170. (defun binary-assemble (codes)
  171.   (let* ((ncodes (length codes))
  172.      (code-vec #-LCL3.0 (lucid::new-code ncodes)
  173.            #+LCL3.0 (lucid::with-current-area 
  174.                 lucid::*READONLY-NON-POINTER-AREA*
  175.                   (lucid::new-code ncodes))))
  176.     (declare (fixnum ncodes))
  177.     (do ((l codes (cdr l))
  178.      (i 0 (1+ i)))
  179.     ((null l) nil)
  180.       (declare (fixnum i))
  181.       (setf (lucid::code-ref code-vec i) (car l)))
  182.     code-vec))
  183.  
  184. ;;;
  185. ;;; Egad! Binary patching!
  186. ;;; See comment following definition of MAKE-TRAMPOLINE -- this is just
  187. ;;;  the "hand-optimized" machine instructions to make it work.
  188. ;;;
  189. (defvar *mattress-pad-code* 
  190.     (binary-assemble
  191.         #+MC68000
  192.         '(#x2A6D #x11 #x246D #x1 #x4EEA #x5)
  193.         #+SPARC
  194.         (ecase (lucid::procedure-length #'lucid::false)
  195.           (5
  196.            '(#xFA07 #x6012 #xDE07 #x7FFE #x81C3 #xFFFE #x100 #x0))
  197.           (8
  198.            `(#xFA07 #x601E #xDE07 #x7FFE #x81C3 #xFFFE #x100 #x0)))
  199.         #+(and BSP (not LCL3.0 ))
  200.         '(#xCD33 #x11 #xCDA3 #x1 #xC19A #x5 #xE889)
  201.         #+(and BSP LCL3.0)
  202.         '(#x7733 #x7153 #xC155 #x5 #xE885)
  203.         #+I386
  204.         '(#x87 #xD2 #x8B #x76 #xE #xFF #x66 #xFE)
  205.         #+VAX
  206.         '(#xD0 #xAC #x11 #x5C #xD0 #xAC #x1 #x57 #x17 #xA7 #x5)
  207.         #+PA
  208.         '(#x4891 #x3C #xE461 #x6530 #x48BF #x3FF9)
  209.                 #+MIPS
  210.                 '(#x8FD4 #x1E #x2785 #x2EEF #xA0 #x8 #x14 #xF000)
  211.                 #-(or MC68000 SPARC BSP I386 VAX PA MIPS)
  212.         '(0 0 0 0)))
  213.  
  214.  
  215. (lucid::defsubst funcallable-instance-p (x)
  216.   (and (lucid::procedurep x)
  217.        (lucid::logbitp& procedure-is-funcallable-instance-bit-position
  218.                         (lucid::procedure-ref x lucid::procedure-flags))))
  219.  
  220. (lucid::defsubst set-funcallable-instance-p (x)
  221.   (if (not (lucid::procedurep x))
  222.       (error "Can't make a non-procedure a fin.")
  223.       (setf (lucid::procedure-ref x lucid::procedure-flags)
  224.         (logior (expt 2 procedure-is-funcallable-instance-bit-position)
  225.             (the fixnum
  226.              (lucid::procedure-ref x lucid::procedure-flags))))))
  227.  
  228.  
  229. (defun allocate-funcallable-instance-1 ()
  230.   #+Prime
  231.   (declare (notinline lucid::new-procedure))    ;fixes a bug in Prime 1.0 in
  232.                                                 ;which new-procedure expands
  233.                                                 ;incorrectly
  234.   (let ((new-fin (lucid::new-procedure fin-size))
  235.     (fin-index fin-size))
  236.     (declare (fixnum fin-index)
  237.          (type lucid::procedure new-fin))
  238.     (dotimes (i (length funcallable-instance-data)) 
  239.       ;; Initialize the new funcallable-instance.  As part of our contract,
  240.       ;; we have to make sure the initial value of all the funcallable
  241.       ;; instance data slots is NIL.
  242.       (decf fin-index)
  243.       (setf (lucid::procedure-ref new-fin fin-index) nil))
  244.     ;;
  245.     ;; "Assemble" the initial function by installing a fast "trampoline" code;
  246.     ;; 
  247.     (setf (lucid::procedure-ref new-fin lucid::procedure-code)
  248.       *mattress-pad-code*)
  249.     ;; Disable argcount checking in the "mattress-pad" code for
  250.     ;;  ports that go through standardized trampolines
  251.     #+PA (setf (sys:procedure-ref new-fin lucid::procedure-arg-count) -1)
  252.     #+MIPS (progn
  253.          (setf (sys:procedure-ref new-fin lucid::procedure-min-args) 0)
  254.          (setf (sys:procedure-ref new-fin lucid::procedure-max-args) 
  255.            call-arguments-limit))
  256.     ;; but start out with the function to be run as an error call.
  257.     (setf (lucid::procedure-ref new-fin fin-trampoline-fun-index)
  258.       #'called-fin-without-function)
  259.     ;; Then mark it as a "fin"
  260.     (set-funcallable-instance-p new-fin)
  261.     new-fin))
  262.  
  263. (defun set-funcallable-instance-function (fin new-value)
  264.   (unless (funcallable-instance-p fin)
  265.     (error "~S is not a funcallable-instance" fin))
  266.   (if (lucid::procedurep new-value)
  267.       (progn
  268.     (setf (lucid::procedure-ref fin fin-trampoline-fun-index) new-value)
  269.     fin)
  270.       (progn 
  271.     (unless (functionp new-value)
  272.       (error "~S is not a function." new-value))
  273.     ;; 'new-value' is an interpreted function.  Install a
  274.     ;; trampoline to call the interpreted function.
  275.     (set-funcallable-instance-function fin
  276.                        (make-trampoline new-value)))))
  277.  
  278. (defmacro funcallable-instance-data-1 (instance data)
  279.   `(lucid::procedure-ref 
  280.        ,instance
  281.        (the fixnum
  282.         (- (- fin-size 1)
  283.            (the fixnum (funcallable-instance-data-position ,data))))))
  284.   
  285. );end of #+Lucid
  286.  
  287.  
  288. ;;;
  289. ;;; In Symbolics Common Lisp, a lexical closure is a pair of an environment
  290. ;;; and an ordinary compiled function.  The environment is represented as
  291. ;;; a CDR-coded list.  I know of no way to add a special bit to say that the
  292. ;;; closure is a FIN, so for now, closures are marked as FINS by storing a
  293. ;;; special marker in the last cell of the environment.
  294. ;;; 
  295. ;;;  The new structure of a fin is:
  296. ;;;     (lex-env lex-fun *marker* fin-data0 fin-data1)
  297. ;;;  The value returned by allocate is a lexical-closure pointing to the start
  298. ;;;  of the fin list.  Benefits are: no longer ever have to copy environments,
  299. ;;;  fins can be much smaller (5 words instead of 18), old environments never
  300. ;;;  get destroyed (so running dcodes dont have the lex env change from under
  301. ;;;  them any longer).
  302. ;;;
  303. ;;;  Most of the fin operations speed up a little (by as much as 30% on a
  304. ;;;  3650), at least one nasty bug is fixed, and so far at least I've not
  305. ;;;  seen any problems at all with this code.   - mike thome (mthome@bbn.com)
  306. ;;;      
  307. #+(and Genera (not Genera-Release-8))
  308. (progn
  309.  
  310. (defvar *funcallable-instance-marker* (list "Funcallable Instance Marker"))
  311.  
  312. (defun allocate-funcallable-instance-1 ()
  313.   (let* ((whole-fin (make-list (+ 3 (length funcallable-instance-data))))
  314.      (new-fin (sys:%make-pointer-offset sys:dtp-lexical-closure
  315.                         whole-fin
  316.                         0)))
  317.     ;;
  318.     ;; note that we DO NOT turn the real lex-closure part of the fin into
  319.     ;; a dotted pair, because (1) the machine doesn't care and (2) if we
  320.     ;; did the garbage collector would reclaim everything after the lexical
  321.     ;; function.
  322.     ;; 
  323.     (setf (sys:%p-contents-offset new-fin 2) *funcallable-instance-marker*)
  324.     (setf (si:lexical-closure-function new-fin)
  325.       #'(lambda (ignore &rest ignore-them-too)
  326.           (declare (ignore ignore ignore-them-too))
  327.           (called-fin-without-function)))
  328.     #+ignore
  329.     (setf (si:lexical-closure-environment new-fin) nil)
  330.     new-fin))
  331.  
  332. (scl:defsubst funcallable-instance-p (x)
  333.   (declare (inline si:lexical-closure-p))
  334.   (and (si:lexical-closure-p x)
  335.        (= (sys:%p-cdr-code (sys:%make-pointer-offset sys:dtp-compiled-function x 1))
  336.       sys:cdr-next)
  337.        (eq (sys:%p-contents-offset x 2) *funcallable-instance-marker*)))
  338.  
  339. (defun set-funcallable-instance-function (fin new-value)
  340.   (cond ((not (funcallable-instance-p fin))
  341.          (error "~S is not a funcallable-instance" fin))
  342.         ((not (or (functionp new-value)
  343.           (and (consp new-value)
  344.                (eq (car new-value) 'si:digested-lambda))))
  345.          (error "~S is not a function." new-value))
  346.         ((and (si:lexical-closure-p new-value)
  347.           (compiled-function-p (si:lexical-closure-function new-value)))
  348.      (let ((env (si:lexical-closure-environment new-value))
  349.            (fn  (si:lexical-closure-function new-value)))
  350.        ;; we only have to copy the pointers!!
  351.        (setf (si:lexical-closure-environment fin) env
  352.          (si:lexical-closure-function fin)    fn)
  353. ;       (dbg:set-env->fin env fin)
  354.        ))
  355.         (t
  356.          (set-funcallable-instance-function fin
  357.                                             (make-trampoline new-value)))))
  358.  
  359. (defun make-trampoline (function)
  360.   (declare (optimize (speed 3) (safety 0)))
  361.   #'(lambda (&rest args)
  362.       #+Genera (declare (dbg:invisible-frame :pcl-internals))
  363.       (apply function args)))
  364.  
  365. (defmacro funcallable-instance-data-1 (fin data)
  366.   `(sys:%p-contents-offset ,fin
  367.                (+ 3 (funcallable-instance-data-position ,data))))
  368.  
  369. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  370.   `(setf (sys:%p-contents-offset ,fin
  371.                  (+ 3 (funcallable-instance-data-position ,data)))
  372.      ,new-value))
  373.  
  374. ;;;
  375. ;;; Make funcallable instances print out properly.
  376. ;;; 
  377. (defvar *print-lexical-closure* nil)
  378.  
  379. (defun pcl-print-lexical-closure (exp stream slashify-p &optional (depth 0))
  380.   (declare (ignore depth))
  381.   (declare (special *boot-state*))
  382.   (if (or (eq *print-lexical-closure* exp)
  383.       (neq *boot-state* 'complete)
  384.       (eq (class-of exp) *the-class-t*))
  385.       (let ((*print-lexical-closure* nil))
  386.     (funcall (original-definition 'si:print-lexical-closure)
  387.          exp stream slashify-p))
  388.       (let ((*print-escape* slashify-p)
  389.         (*print-lexical-closure* exp))
  390.     (print-object exp stream))))
  391.  
  392. (unless (boundp '*boot-state*)
  393.   (setq *boot-state* nil))
  394.  
  395. (redefine-function 'si:print-lexical-closure 'pcl-print-lexical-closure)
  396.  
  397. (defvar *function-name-level* 0)
  398.  
  399. (defun pcl-function-name (function &rest other-args)
  400.   (if (and (eq *boot-state* 'complete)
  401.        (funcallable-instance-p function)
  402.        (generic-function-p function)
  403.        (<= *function-name-level* 2))
  404.       (let ((*function-name-level* (1+ *function-name-level*)))
  405.     (generic-function-name function))
  406.       (apply (original-definition 'si:function-name) function other-args)))
  407.  
  408. (redefine-function 'si:function-name 'pcl-function-name)
  409.  
  410. (defun pcl-arglist (function &rest other-args)
  411.   (let ((defn nil))
  412.     (cond ((and (funcallable-instance-p function)
  413.         (generic-function-p function))
  414.        (generic-function-pretty-arglist function))
  415.       ((and (sys:validate-function-spec function)
  416.         (sys:fdefinedp function)
  417.         (setq defn (sys:fdefinition function))
  418.         (funcallable-instance-p defn)
  419.         (generic-function-p defn))
  420.        (generic-function-pretty-arglist defn))
  421.       (t (apply (original-definition 'zl:arglist) function other-args)))))
  422.  
  423. (redefine-function 'zl:arglist 'pcl-arglist)
  424.  
  425.  
  426. ;;;
  427. ;;; This code is adapted from frame-lexical-environment and frame-function.
  428. ;;;
  429. #||
  430. dbg:
  431. (progn
  432.  
  433. (defvar *old-frame-function*)
  434.  
  435. (defvar *inside-new-frame-function* nil)
  436.  
  437. (defun new-frame-function (frame)
  438.   (let* ((fn (funcall *old-frame-function* frame))
  439.      (location (%pointer-plus frame #+imach (defstorage-size stack-frame) #-imach 0))
  440.      (env? #+3600 (location-contents location)
  441.            #+imach (%memory-read location :cycle-type %memory-scavenge)))
  442.     (or (when (cl:consp env?)
  443.       (let ((l2 (last2 env?)))
  444.         (when (eq (car l2) '.this-is-a-dfun.)
  445.           (cadr l2))))
  446.     fn)))
  447.  
  448. (defun pcl::doctor-dfun-for-the-debugger (gf dfun)
  449.   (when (sys:lexical-closure-p dfun)
  450.     (let* ((env (si:lexical-closure-environment dfun))
  451.        (l2 (last2 env)))
  452.       (unless (eq (car l2) '.this-is-a-dfun.)
  453.     (setf (si:lexical-closure-environment dfun)
  454.           (nconc env (list '.this-is-a-dfun. gf))))))
  455.   dfun)
  456.  
  457. (defun last2 (l)
  458.   (labels ((scan (2ago tail)
  459.          (if (null tail)
  460.          2ago
  461.          (if (cl:consp tail)
  462.              (scan (cdr 2ago) (cdr tail))
  463.              nil))))
  464.     (and (cl:consp l)
  465.      (cl:consp (cdr l))
  466.      (scan l (cddr l)))))
  467.  
  468. (eval-when (load)
  469.   (unless (boundp '*old-frame-function*)
  470.     (setq *old-frame-function* #'frame-function)
  471.     (setf (cl:symbol-function 'frame-function) 'new-frame-function)))
  472.  
  473. )
  474. ||#
  475.  
  476. );end of #+Genera
  477.  
  478.  
  479.  
  480. ;;;
  481. ;;; In Genera 8.0, we use a real funcallable instance (from Genera CLOS) for this.
  482. ;;; This minimizes the subprimitive mucking around.
  483. ;;;
  484. #+(and Genera Genera-Release-8)
  485. (progn
  486.  
  487. (clos-internals::ensure-class
  488.   'pcl-funcallable-instance
  489.   :direct-superclasses '(clos-internals:funcallable-instance)
  490.   :slots `((:name function
  491.         :initform #'(lambda (ignore &rest ignore-them-too)
  492.               (declare (ignore ignore ignore-them-too))
  493.               (called-fin-without-function))
  494.         :initfunction ,#'(lambda nil
  495.                    #'(lambda (ignore &rest ignore-them-too)
  496.                    (declare (ignore ignore ignore-them-too))
  497.                    (called-fin-without-function))))
  498.        ,@(mapcar #'(lambda (slot) `(:name ,slot)) funcallable-instance-data))
  499.   :metaclass 'clos:funcallable-standard-class)
  500.  
  501. (defun pcl-funcallable-instance-trampoline (extra-arg &rest args)
  502.   (apply (sys:%instance-ref (clos-internals::%dispatch-instance-from-extra-argument extra-arg)
  503.                 3)
  504.      args))
  505.  
  506. (defun allocate-funcallable-instance-1 ()
  507.   (let ((fin (clos:make-instance 'pcl-funcallable-instance)))
  508.     (setf (clos-internals::%funcallable-instance-function fin)
  509.       #'pcl-funcallable-instance-trampoline)
  510.     (setf (clos-internals::%funcallable-instance-extra-argument fin)
  511.       (sys:%make-pointer sys:dtp-instance
  512.                  (clos-internals::%funcallable-instance-extra-argument fin)))
  513.     (setf (clos:slot-value fin 'clos-internals::funcallable-instance) fin)
  514.     fin))
  515.  
  516. (scl:defsubst funcallable-instance-p (x)
  517.   (and (sys:funcallable-instance-p x)
  518.        (eq (clos-internals::%funcallable-instance-function x)
  519.        #'pcl-funcallable-instance-trampoline)))
  520.  
  521. (defun set-funcallable-instance-function (fin new-value)
  522.   (setf (clos:slot-value fin 'function) new-value))
  523.  
  524. (defmacro funcallable-instance-data-1 (fin data)
  525.   `(clos-internals:%funcallable-instance-ref
  526.      ,fin (+ 4 (funcallable-instance-data-position ,data))))
  527.  
  528. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  529.   `(setf (clos-internals:%funcallable-instance-ref
  530.        ,fin (+ 4 (funcallable-instance-data-position ,data)))
  531.      ,new-value))
  532.  
  533. (clos:defmethod clos:print-object ((fin pcl-funcallable-instance) stream)
  534.   (print-object fin stream))
  535.  
  536. (clos:defmethod clos-internals:debugging-information-function ((fin pcl-funcallable-instance))
  537.   nil)
  538.  
  539. (clos:defmethod clos-internals:function-name-object ((fin pcl-funcallable-instance))
  540.   (declare (special *boot-state*))
  541.   (if (and (eq *boot-state* 'complete)
  542.        (generic-function-p fin))
  543.       (generic-function-name fin)
  544.       fin))
  545.  
  546. (clos:defmethod clos-internals:arglist-object ((fin pcl-funcallable-instance))
  547.   (declare (special *boot-state*))
  548.   (if (and (eq *boot-state* 'complete)
  549.        (generic-function-p fin))
  550.       (generic-function-pretty-arglist fin)
  551.       '(&rest args)))
  552.  
  553. );end of #+Genera
  554.  
  555.  
  556.  
  557. #+Cloe-Runtime
  558. (progn
  559.  
  560. (defconstant funcallable-instance-closure-slots 5)
  561. (defconstant funcallable-instance-closure-size
  562.          (+ funcallable-instance-closure-slots (length funcallable-instance-data) 1))
  563.  
  564. #-CLOE-Release-2 (progn
  565.  
  566. (defun allocate-funcallable-instance-1 ()
  567.   (let ((data (system::make-funcallable-structure 'funcallable-instance
  568.                           funcallable-instance-closure-size)))
  569.     (setf (system::%trampoline-ref data funcallable-instance-closure-slots)
  570.       'funcallable-instance)
  571.     (set-funcallable-instance-function
  572.       data
  573.       #'(lambda (&rest ignore-them-too)
  574.       (declare (ignore ignore-them-too))
  575.       (called-fin-without-function)))
  576.     data))
  577.  
  578. (proclaim '(inline funcallable-instance-p))
  579. (defun funcallable-instance-p (x)
  580.   (and (typep x 'system::trampoline)
  581.        (= (system::%trampoline-data-length x) funcallable-instance-closure-size)
  582.        (eq (system::%trampoline-ref x funcallable-instance-closure-slots)
  583.        'funcallable-instance)))
  584.  
  585. (defun set-funcallable-instance-function (fin new-value)
  586.   (when (not (funcallable-instance-p fin))
  587.     (error "~S is not a funcallable-instance" fin))
  588.   (etypecase new-value
  589.     (system::trampoline
  590.       (let ((length (system::%trampoline-data-length new-value)))
  591.     (cond ((> length funcallable-instance-closure-slots)
  592.            (set-funcallable-instance-function
  593.          fin
  594.          #'(lambda (&rest args)
  595.              (declare (sys:downward-rest-argument))
  596.              (apply new-value args))))
  597.           (t
  598.            (setf (system::%trampoline-function fin)
  599.              (system::%trampoline-function new-value))
  600.            (dotimes (i length)
  601.          (setf (system::%trampoline-ref fin i)
  602.                (system::%trampoline-ref new-value i)))))))
  603.     (compiled-function
  604.       (setf (system::%trampoline-function fin) new-value))
  605.     (function
  606.       (set-funcallable-instance-function
  607.     fin
  608.     #'(lambda (&rest args)
  609.         (declare (sys:downward-rest-argument))
  610.         (apply new-value args))))))
  611.  
  612. (defmacro funcallable-instance-data-1 (fin data)
  613.   `(system::%trampoline-ref ,fin (+ funcallable-instance-closure-slots
  614.                     1 (funcallable-instance-data-position ,data))))
  615.  
  616. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  617.   `(setf (system::%trampoline-ref ,fin (+ funcallable-instance-closure-slots
  618.                       1 (funcallable-instance-data-position ,data)))
  619.      ,new-value))
  620.  
  621. )
  622.  
  623. #+CLOE-Release-2 (progn
  624.  
  625. (defun allocate-funcallable-instance-1 ()
  626.   (let ((data (si::cons-closure funcallable-instance-closure-size)))
  627.     (setf (si::closure-ref data funcallable-instance-closure-slots) 'funcallable-instance)
  628.     (set-funcallable-instance-function
  629.       data
  630.       #'(lambda (&rest ignore-them-too)
  631.       (declare (ignore ignore-them-too))
  632.       (error "Called a FIN without first setting its function.")))
  633.     data))
  634.  
  635. (proclaim '(inline funcallable-instance-p))
  636. (defun funcallable-instance-p (x)
  637.   (and (si::closurep x)
  638.        (= (si::closure-length x) funcallable-instance-closure-size)
  639.        (eq (si::closure-ref x funcallable-instance-closure-slots) 'funcallable-instance)))
  640.  
  641. (defun set-funcallable-instance-function (fin new-value)
  642.   (when (not (funcallable-instance-p fin))
  643.     (error "~S is not a funcallable-instance" fin))
  644.   (etypecase new-value
  645.     (si::closure
  646.       (let ((length (si::closure-length new-value)))
  647.     (cond ((> length funcallable-instance-closure-slots)
  648.            (set-funcallable-instance-function
  649.          fin
  650.          #'(lambda (&rest args)
  651.              (declare (sys:downward-rest-argument))
  652.              (apply new-value args))))
  653.           (t
  654.            (setf (si::closure-function fin) (si::closure-function new-value))
  655.            (dotimes (i length)
  656.          (si::object-set fin (+ i 3) (si::object-ref new-value (+ i 3))))))))
  657.     (compiled-function
  658.       (setf (si::closure-function fin) new-value))
  659.     (function
  660.       (set-funcallable-instance-function
  661.     fin
  662.     #'(lambda (&rest args)
  663.         (declare (sys:downward-rest-argument))
  664.         (apply new-value args))))))
  665.  
  666. (defmacro funcallable-instance-data-1 (fin data)
  667.   `(si::closure-ref ,fin (+ funcallable-instance-closure-slots
  668.                 1 (funcallable-instance-data-position ,data))))
  669.  
  670. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  671.   `(setf (si::closure-ref ,fin (+ funcallable-instance-closure-slots
  672.                   1 (funcallable-instance-data-position ,data)))
  673.      ,new-value))
  674.  
  675. )
  676.  
  677. )
  678.  
  679.  
  680. ;;;
  681. ;;;
  682. ;;; In Xerox Common Lisp, a lexical closure is a pair of an environment and
  683. ;;; CCODEP.  The environment is represented as a block.  There is space in
  684. ;;; the top 8 bits of the pointers to the CCODE and the environment to use
  685. ;;; to mark the closure as being a FIN.
  686. ;;;
  687. ;;; To help the debugger figure out when it has found a FIN on the stack, we
  688. ;;; reserve the last element of the closure environment to use to point back
  689. ;;; to the actual fin.
  690. ;;;
  691. ;;; Note that there is code in xerox-low which lets us access the fields of
  692. ;;; compiled-closures and which defines the closure-overlay record.  That
  693. ;;; code is there because there are some clients of it in that file.
  694. ;;;      
  695. #+Xerox
  696. (progn
  697.  
  698. ;; Don't be fooled.  We actually allocate one bigger than this to have a place
  699. ;; to store the backpointer to the fin.  -smL
  700. (defconstant funcallable-instance-closure-size 15)
  701.  
  702. ;; This is only used in the file PCL-ENV.
  703. (defvar *fin-env-type*
  704.   (type-of (il:\\allocblock (1+ funcallable-instance-closure-size) t)))
  705.  
  706. ;; Well, Gregor may be too proud to hack xpointers, but bvm and I aren't. -smL
  707.  
  708. (defstruct fin-env-pointer
  709.   (pointer nil :type il:fullxpointer))
  710.  
  711. (defun fin-env-fin (fin-env)
  712.   (fin-env-pointer-pointer
  713.    (il:\\getbaseptr fin-env (* funcallable-instance-closure-size 2))))
  714.  
  715. (defun |set fin-env-fin| (fin-env new-value)
  716.   (il:\\rplptr fin-env (* funcallable-instance-closure-size 2)
  717.            (make-fin-env-pointer :pointer new-value))
  718.   new-value)
  719.  
  720. (defsetf fin-env-fin |set fin-env-fin|)
  721.  
  722. ;; The finalization function that will clean up the backpointer from the
  723. ;; fin-env to the fin.  This needs to be careful to not cons at all.  This
  724. ;; depends on there being no other finalization function on compiled-closures,
  725. ;; since there is only one finalization function per datatype.  Too bad.  -smL
  726. (defun finalize-fin (fin)
  727.   ;; This could use the fn funcallable-instance-p, but if we get here we know
  728.   ;; that this is a closure, so we can skip that test.
  729.   (when (il:fetch (closure-overlay funcallable-instance-p) il:of fin)
  730.     (let ((env (il:fetch (il:compiled-closure il:environment) il:of fin)))
  731.       (when env
  732.     (setq env
  733.           (il:\\getbaseptr env (* funcallable-instance-closure-size 2)))
  734.     (when (il:typep env 'fin-env-pointer) 
  735.       (setf (fin-env-pointer-pointer env) nil)))))
  736.   nil)                    ;Return NIL so GC can proceed
  737.  
  738. (eval-when (load)
  739.   ;; Install the above finalization function.
  740.   (when (fboundp 'finalize-fin)
  741.     (il:\\set.finalization.function 'il:compiled-closure 'finalize-fin)))
  742.  
  743. (defun allocate-funcallable-instance-1 ()
  744.   (let* ((env (il:\\allocblock (1+ funcallable-instance-closure-size) t))
  745.          (fin (il:make-compiled-closure nil env)))
  746.     (setf (fin-env-fin env) fin)
  747.     (il:replace (closure-overlay funcallable-instance-p) il:of fin il:with 't)
  748.     (set-funcallable-instance-function fin
  749.       #'(lambda (&rest ignore)
  750.           (declare (ignore ignore))
  751.       (called-fin-without-function)))
  752.     fin))
  753.  
  754. (xcl:definline funcallable-instance-p (x)
  755.   (and (typep x 'il:compiled-closure)
  756.        (il:fetch (closure-overlay funcallable-instance-p) il:of x)))
  757.  
  758. (defun set-funcallable-instance-function (fin new)
  759.   (cond ((not (funcallable-instance-p fin))
  760.          (error "~S is not a funcallable-instance" fin))
  761.         ((not (functionp new))
  762.          (error "~S is not a function." new))
  763.         ((typep new 'il:compiled-closure)
  764.          (let* ((fin-env
  765.                   (il:fetch (il:compiled-closure il:environment) il:of fin))
  766.                 (new-env
  767.                   (il:fetch (il:compiled-closure il:environment) il:of new))
  768.                 (new-env-size (if new-env (il:\\#blockdatacells new-env) 0))
  769.                 (fin-env-size (- funcallable-instance-closure-size
  770.                                  (length funcallable-instance-data))))
  771.            (cond ((and new-env
  772.                (<= new-env-size fin-env-size))
  773.           (dotimes (i fin-env-size)
  774.             (il:\\rplptr fin-env
  775.                  (* i 2)
  776.                  (if (< i new-env-size)
  777.                      (il:\\getbaseptr new-env (* i 2))
  778.                      nil)))
  779.           (setf (compiled-closure-fnheader fin)
  780.             (compiled-closure-fnheader new)))
  781.                  (t
  782.                   (set-funcallable-instance-function
  783.                     fin
  784.                     (make-trampoline new))))))
  785.         (t
  786.          (set-funcallable-instance-function fin
  787.                                             (make-trampoline new)))))
  788.  
  789. (defun make-trampoline (function)
  790.   #'(lambda (&rest args)
  791.       (apply function args)))
  792.  
  793.         
  794. (defmacro funcallable-instance-data-1 (fin data)
  795.   `(il:\\getbaseptr (il:fetch (il:compiled-closure il:environment) il:of ,fin)
  796.             (* (- funcallable-instance-closure-size
  797.               (funcallable-instance-data-position ,data)
  798.               1)            ;Reserve last element to
  799.                         ;point back to actual FIN!
  800.                2)))
  801.  
  802. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  803.   `(il:\\rplptr (il:fetch (il:compiled-closure il:environment) il:of ,fin)
  804.         (* (- funcallable-instance-closure-size
  805.               (funcallable-instance-data-position ,data)
  806.               1)
  807.            2)
  808.         ,new-value))
  809.  
  810. );end of #+Xerox
  811.  
  812.  
  813. ;;;
  814. ;;; In Franz Common Lisp ExCL
  815. ;;; This code was originally written by:
  816. ;;;   jkf%franz.uucp@berkeley.edu
  817. ;;; and hacked by:
  818. ;;;   smh%franz.uucp@berkeley.edu
  819.  
  820. #+ExCL
  821. (progn
  822.  
  823. (defconstant funcallable-instance-flag-bit #x1)
  824.  
  825. (defun funcallable-instance-p (x)
  826.    (and (excl::function-object-p x)
  827.         (eq funcallable-instance-flag-bit
  828.             (logand (excl::fn_flags x)
  829.                     funcallable-instance-flag-bit))))
  830.  
  831. (defun make-trampoline (function)
  832.   #'(lambda (&rest args)
  833.       (apply function args)))
  834.  
  835. ;; We initialize a fin's procedure function to this because
  836. ;; someone might try to funcall it before it has been set up.
  837. (defun init-fin-fun (&rest ignore)
  838.   (declare (ignore ignore))
  839.   (called-fin-without-function))
  840.  
  841.  
  842. (eval-when (eval) 
  843.   (compile 'make-trampoline)
  844.   (compile 'init-fin-fun))
  845.  
  846.  
  847. ;; new style
  848. #+(and gsgc (not sun4) (not cray) (not mips))
  849. (progn
  850. ;; set-funcallable-instance-function must work by overwriting the fin itself
  851. ;; because the fin must maintain EQ identity.
  852. ;; Because the gsgc time needs several of the fields in the function object
  853. ;; at gc time in order to walk the stack frame, it is important never to bash
  854. ;; a function object that is active in a frame on the stack.  Besides, changing
  855. ;; the functions closure vector, not to mention overwriting its constant
  856. ;; vector, would scramble it's execution when that stack frame continues.
  857. ;; Therefore we represent a fin as a funny compiled-function object.
  858. ;; The code vector of this object has some hand-coded instructions which
  859. ;; do a very fast jump into the real fin handler function.  The function
  860. ;; which is the fin object *never* creates a frame on the stack.
  861.   
  862.  
  863. (defun allocate-funcallable-instance-1 ()
  864.   (let ((fin (compiler::.primcall 'sys::new-function))
  865.     (init #'init-fin-fun)
  866.     (mattress-fun #'funcallable-instance-mattress-pad))
  867.     (setf (excl::fn_symdef fin) 'anonymous-fin)
  868.     (setf (excl::fn_constant fin) init)
  869.     (setf (excl::fn_code fin)        ; this must be before fn_start
  870.       (excl::fn_code mattress-fun))
  871.     (setf (excl::fn_start fin) (excl::fn_start mattress-fun))
  872.     (setf (excl::fn_flags fin) (logior (excl::fn_flags init)
  873.                        funcallable-instance-flag-bit))
  874.     (setf (excl::fn_closure fin)
  875.       (make-array (length funcallable-instance-data)))
  876.  
  877.     fin))
  878.  
  879. ;; This function gets its code vector modified with a hand-coded fast jump
  880. ;; to the function that is stored in place of its constant vector.
  881. ;; This function is never linked in and never appears on the stack.
  882.  
  883. (defun funcallable-instance-mattress-pad ()
  884.   (declare (optimize (speed 3) (safety 0)))
  885.   'nil)
  886.  
  887. (eval-when (eval)
  888.   (compile 'funcallable-instance-mattress-pad))
  889.  
  890.  
  891. #+(and excl (target-class s))
  892. (eval-when (load eval)
  893.   (let ((codevec (excl::fn_code
  894.           (symbol-function 'funcallable-instance-mattress-pad))))
  895.     ;; The entire code vector wants to be:
  896.     ;;   move.l  7(a2),a2     ;#x246a0007
  897.     ;;   jmp     1(a2)        ;#x4eea0001
  898.     (setf (aref codevec 0) #x246a
  899.       (aref codevec 1) #x0007
  900.       (aref codevec 2) #x4eea
  901.       (aref codevec 3) #x0001))
  902. )
  903.  
  904. #+(and excl (target-class a))
  905. (eval-when (load eval)
  906.   (let ((codevec (excl::fn_code
  907.           (symbol-function 'funcallable-instance-mattress-pad))))
  908.     ;; The entire code vector wants to be:
  909.     ;;   l       r5,15(r5)    ;#x5850500f
  910.     ;;   l       r15,11(r5)   ;#x58f0500b
  911.     ;;   br      r15          ;#x07ff
  912.     (setf (aref codevec 0) #x5850
  913.       (aref codevec 1) #x500f
  914.       (aref codevec 2) #x58f0
  915.       (aref codevec 3) #x500b
  916.       (aref codevec 4) #x07ff
  917.       (aref codevec 5) #x0000))
  918.   )
  919.  
  920. #+(and excl (target-class i))
  921. (eval-when (load eval)
  922.   (let ((codevec (excl::fn_code
  923.           (symbol-function 'funcallable-instance-mattress-pad))))
  924.     ;; The entire code vector wants to be:
  925.     ;;   movl  7(edx),edx     ;#x07528b
  926.     ;;   jmp   *3(edx)        ;#x0362ff
  927.     (setf (aref codevec 0) #x8b
  928.       (aref codevec 1) #x52
  929.       (aref codevec 2) #x07
  930.       (aref codevec 3) #xff
  931.       (aref codevec 4) #x62
  932.       (aref codevec 5) #x03))
  933. )
  934.  
  935. (defun funcallable-instance-data-1 (instance data)
  936.   (let ((constant (excl::fn_closure instance)))
  937.     (svref constant (funcallable-instance-data-position data))))
  938.  
  939. (defsetf funcallable-instance-data-1 set-funcallable-instance-data-1)
  940.  
  941. (defun set-funcallable-instance-data-1 (instance data new-value)
  942.   (let ((constant (excl::fn_closure instance)))
  943.     (setf (svref constant (funcallable-instance-data-position data))
  944.           new-value)))
  945.  
  946. (defun set-funcallable-instance-function (fin new-function)
  947.   (unless (funcallable-instance-p fin)
  948.     (error "~S is not a funcallable-instance" fin))
  949.   (unless (functionp new-function)
  950.     (error "~S is not a function." new-function))
  951.   (setf (excl::fn_constant fin)
  952.     (if (excl::function-object-p new-function)
  953.         new-function
  954.         ;; The new-function is an interpreted function.
  955.         ;; Install a trampoline to call the interpreted function.
  956.         (make-trampoline new-function))))
  957.  
  958.  
  959. )  ;; end sun3
  960.  
  961.  
  962. #+(and gsgc (or sun4 mips))
  963. (progn
  964.  
  965. (eval-when (compile load eval)
  966.   (defconstant funcallable-instance-constant-count 15)
  967.   )
  968.  
  969. (defun allocate-funcallable-instance-1 ()
  970.   (let ((new-fin (compiler::.primcall 
  971.            'sys::new-function
  972.            funcallable-instance-constant-count)))
  973.     ;; Have to set the procedure function to something for two reasons.
  974.     ;;   1. someone might try to funcall it.
  975.     ;;   2. the flag bit that says the procedure is a funcallable
  976.     ;;      instance is set by set-funcallable-instance-function.
  977.     (set-funcallable-instance-function new-fin #'init-fin-fun)
  978.     new-fin))
  979.  
  980. (defun set-funcallable-instance-function (fin new-value)
  981.   ;; we actually only check for a function object since
  982.   ;; this is called before the funcallable instance flag is set
  983.   (unless (excl::function-object-p fin)
  984.     (error "~S is not a funcallable-instance" fin))
  985.  
  986.   (cond ((not (functionp new-value))
  987.          (error "~S is not a function." new-value))
  988.         ((not (excl::function-object-p new-value))
  989.          ;; new-value is an interpreted function.  Install a
  990.          ;; trampoline to call the interpreted function.
  991.          (set-funcallable-instance-function fin (make-trampoline new-value)))
  992.     ((> (+ (excl::function-constant-count new-value)
  993.            (length funcallable-instance-data))
  994.         funcallable-instance-constant-count)
  995.      ; can't fit, must trampoline
  996.      (set-funcallable-instance-function fin (make-trampoline new-value)))
  997.         (t
  998.          ;; tack the instance variables at the end of the constant vector
  999.      
  1000.          (setf (excl::fn_code fin)    ; this must be before fn_start
  1001.            (excl::fn_code new-value))
  1002.          (setf (excl::fn_start fin) (excl::fn_start new-value))
  1003.          
  1004.          (setf (excl::fn_closure fin) (excl::fn_closure new-value))
  1005.      ; only replace the symdef slot if the new value is an 
  1006.      ; interned symbol or some other object (like a function spec)
  1007.      (let ((newsym (excl::fn_symdef new-value)))
  1008.        (excl:if* (and newsym (or (not (symbolp newsym))
  1009.                 (symbol-package newsym)))
  1010.           then (setf (excl::fn_symdef fin) newsym)))
  1011.          (setf (excl::fn_formals fin) (excl::fn_formals new-value))
  1012.          (setf (excl::fn_cframe-size fin) (excl::fn_cframe-size new-value))
  1013.      (setf (excl::fn_locals fin) (excl::fn_locals new-value))
  1014.          (setf (excl::fn_flags fin) (logior (excl::fn_flags new-value)
  1015.                                             funcallable-instance-flag-bit))
  1016.      
  1017.      ;; on a sun4 we copy over the constants
  1018.      (dotimes (i (excl::function-constant-count new-value))
  1019.        (setf (excl::function-constant fin i) 
  1020.          (excl::function-constant new-value i)))
  1021.      ;(format t "all done copy from ~s to ~s" new-value fin)
  1022.      )))
  1023.  
  1024. (defmacro funcallable-instance-data-1 (instance data)
  1025.   `(excl::function-constant ,instance 
  1026.                (- funcallable-instance-constant-count
  1027.                   (funcallable-instance-data-position ,data)
  1028.                   1)))
  1029.  
  1030. ) ;; end sun4 or mips
  1031.  
  1032. #+(and gsgc cray)
  1033. (progn
  1034.  
  1035. ;; The cray is like the sun4 in that the constant vector is included in the  
  1036. ;; function object itself.  But a mattress pad must be used anyway, because
  1037. ;; the function start address is copied in the symbol object, and cannot be
  1038. ;; updated when the fin is changed.  
  1039. ;; We place the funcallable-instance-function into the first constant slot,  
  1040. ;; and leave enough constant slots after that for the instance data.
  1041.  
  1042. (eval-when (compile load eval)
  1043.   (defconstant fin-fun-slot 0)
  1044.   (defconstant fin-instance-data-slot 1)
  1045.   )
  1046.  
  1047.  
  1048. ;; We initialize a fin's procedure function to this because
  1049. ;; someone might try to funcall it before it has been set up.
  1050. (defun init-fin-fun (&rest ignore)
  1051.   (declare (ignore ignore))
  1052.   (called-fin-without-function))
  1053.  
  1054. (defun allocate-funcallable-instance-1 ()
  1055.   (let ((fin (compiler::.primcall 'sys::new-function
  1056.             (1+ (length funcallable-instance-data))
  1057.             "funcallable-instance"))
  1058.     (init #'init-fin-fun)
  1059.     (mattress-fun #'funcallable-instance-mattress-pad))
  1060.     (setf (excl::fn_symdef fin) 'anonymous-fin)
  1061.     (setf (excl::function-constant fin fin-fun-slot) init)
  1062.     (setf (excl::fn_code fin)        ; this must be before fn_start
  1063.       (excl::fn_code mattress-fun))
  1064.     (setf (excl::fn_start fin) (excl::fn_start mattress-fun))
  1065.     (setf (excl::fn_flags fin) (logior (excl::fn_flags init)
  1066.                        funcallable-instance-flag-bit))
  1067.     
  1068.     fin))
  1069.  
  1070. ;; This function gets its code vector modified with a hand-coded fast jump
  1071. ;; to the function that is stored in place of its constant vector.
  1072. ;; This function is never linked in and never appears on the stack.
  1073.  
  1074. (defun funcallable-instance-mattress-pad ()
  1075.   (declare (optimize (speed 3) (safety 0)))
  1076.   'nil)
  1077.  
  1078. (eval-when (eval)
  1079.   (compile 'funcallable-instance-mattress-pad)
  1080.   (compile 'init-fin-fun))
  1081.  
  1082. (eval-when (load eval)
  1083.   (let ((codevec (excl::fn_code
  1084.           (symbol-function 'funcallable-instance-mattress-pad))))
  1085.     ;; The entire code vector wants to be:
  1086.     ;;   a1  b77
  1087.     ;;   a2  12,a1
  1088.     ;;   a1 1,a2
  1089.     ;;   b77 a2
  1090.     ;;   b76 a1
  1091.     ;;   j   b76
  1092.     (setf (aref codevec 0) #o024177
  1093.       (aref codevec 1) #o101200 (aref codevec 2) 12
  1094.       (aref codevec 3) #o102100 (aref codevec 4) 1
  1095.       (aref codevec 5) #o025277
  1096.       (aref codevec 6) #o025176
  1097.       (aref codevec 7) #o005076
  1098.       ))
  1099. )
  1100.  
  1101. (defmacro funcallable-instance-data-1 (instance data)
  1102.   `(excl::function-constant ,instance 
  1103.                 (+ (funcallable-instance-data-position ,data)
  1104.                    fin-instance-dtat-slot)))
  1105.  
  1106.  
  1107. (defun set-funcallable-instance-function (fin new-function)
  1108.   (unless (funcallable-instance-p fin)
  1109.     (error "~S is not a funcallable-instance" fin))
  1110.   (unless (functionp new-function)
  1111.     (error "~S is not a function." new-function))
  1112.   (setf (excl::function-constant fin fin-fun-slot)
  1113.     (if (excl::function-object-p new-function)
  1114.     new-function
  1115.     ;; The new-function is an interpreted function.
  1116.     ;; Install a trampoline to call the interpreted function.
  1117.     (make-trampoline new-function))))
  1118.  
  1119. ) ;; end cray
  1120.  
  1121. #-gsgc
  1122. (progn
  1123.  
  1124. (defun allocate-funcallable-instance-1 ()
  1125.   (let ((new-fin (compiler::.primcall 'sys::new-function)))
  1126.     ;; Have to set the procedure function to something for two reasons.
  1127.     ;;   1. someone might try to funcall it.
  1128.     ;;   2. the flag bit that says the procedure is a funcallable
  1129.     ;;      instance is set by set-funcallable-instance-function.
  1130.     (set-funcallable-instance-function new-fin #'init-fin-fn)
  1131.     new-fin))
  1132.  
  1133. (defun set-funcallable-instance-function (fin new-value)
  1134.   ;; we actually only check for a function object since
  1135.   ;; this is called before the funcallable instance flag is set
  1136.   (unless (excl::function-object-p fin)
  1137.     (error "~S is not a funcallable-instance" fin))
  1138.   (cond ((not (functionp new-value))
  1139.          (error "~S is not a function." new-value))
  1140.         ((not (excl::function-object-p new-value))
  1141.          ;; new-value is an interpreted function.  Install a
  1142.          ;; trampoline to call the interpreted function.
  1143.          (set-funcallable-instance-function fin (make-trampoline new-value)))
  1144.         (t
  1145.          ;; tack the instance variables at the end of the constant vector
  1146.          (setf (excl::fn_start fin) (excl::fn_start new-value))
  1147.          (setf (excl::fn_constant fin) (add-instance-vars
  1148.                                         (excl::fn_constant new-value)
  1149.                                         (excl::fn_constant fin)))
  1150.          (setf (excl::fn_closure fin) (excl::fn_closure new-value))
  1151.      ;; In versions prior to 2.0. comment the next line and any other
  1152.      ;; references to fn_symdef or fn_locals.
  1153.      (setf (excl::fn_symdef fin) (excl::fn_symdef new-value))
  1154.          (setf (excl::fn_code fin) (excl::fn_code new-value))
  1155.          (setf (excl::fn_formals fin) (excl::fn_formals new-value))
  1156.          (setf (excl::fn_cframe-size fin) (excl::fn_cframe-size new-value))
  1157.      (setf (excl::fn_locals fin) (excl::fn_locals new-value))
  1158.          (setf (excl::fn_flags fin) (logior (excl::fn_flags new-value)
  1159.                                             funcallable-instance-flag-bit)))))
  1160.  
  1161. (defun add-instance-vars (cvec old-cvec)
  1162.   ;; create a constant vector containing everything in the given constant
  1163.   ;; vector plus space for the instance variables
  1164.   (let* ((nconstants (cond (cvec (length cvec)) (t 0)))
  1165.          (ndata (length funcallable-instance-data))
  1166.          (old-cvec-length (if old-cvec (length old-cvec) 0))
  1167.          (new-cvec nil))
  1168.     (cond ((<= (+ nconstants ndata)  old-cvec-length)
  1169.            (setq new-cvec old-cvec))
  1170.           (t
  1171.            (setq new-cvec (make-array (+ nconstants ndata)))
  1172.            (when old-cvec
  1173.              (dotimes (i ndata)
  1174.                (setf (svref new-cvec (- (+ nconstants ndata) i 1))
  1175.                      (svref old-cvec (- old-cvec-length i 1)))))))
  1176.     
  1177.     (dotimes (i nconstants) (setf (svref new-cvec i) (svref cvec i)))
  1178.     
  1179.     new-cvec))
  1180.  
  1181. (defun funcallable-instance-data-1 (instance data)
  1182.   (let ((constant (excl::fn_constant instance)))
  1183.     (svref constant (- (length constant)
  1184.                        (1+ (funcallable-instance-data-position data))))))
  1185.  
  1186. (defsetf funcallable-instance-data-1 set-funcallable-instance-data-1)
  1187.  
  1188. (defun set-funcallable-instance-data-1 (instance data new-value)
  1189.   (let ((constant (excl::fn_constant instance)))
  1190.     (setf (svref constant (- (length constant) 
  1191.                              (1+ (funcallable-instance-data-position data))))
  1192.           new-value)))
  1193.  
  1194. );end #-gsgc
  1195.  
  1196. );end of #+ExCL
  1197.  
  1198.  
  1199. ;;;
  1200. ;;; In Vaxlisp
  1201. ;;; This code was originally written by:
  1202. ;;;    vanroggen%bach.DEC@DECWRL.DEC.COM
  1203. ;;; 
  1204. #+(and dec vax common)
  1205. (progn
  1206.  
  1207. ;;; The following works only in Version 2 of VAXLISP, and will have to
  1208. ;;; be replaced for later versions.
  1209.  
  1210. (defun allocate-funcallable-instance-1 ()
  1211.   (list 'system::%compiled-closure%
  1212.         ()
  1213.         #'(lambda (&rest args)
  1214.             (declare (ignore args))
  1215.         (called-fin-without-function))
  1216.         (make-array (length funcallable-instance-data))))
  1217.  
  1218. (proclaim '(inline funcallable-instance-p))
  1219. (defun funcallable-instance-p (x)
  1220.   (and (consp x)
  1221.        (eq (car x) 'system::%compiled-closure%)
  1222.        (not (null (cdddr x)))))
  1223.  
  1224. (defun set-funcallable-instance-function (fin func)
  1225.   (cond ((not (funcallable-instance-p fin))
  1226.          (error "~S is not a funcallable-instance" fin))
  1227.         ((not (functionp func))
  1228.          (error "~S is not a function" func))
  1229.         ((and (consp func) (eq (car func) 'system::%compiled-closure%))
  1230.          (setf (cadr fin) (cadr func)
  1231.                (caddr fin) (caddr func)))
  1232.         (t (set-funcallable-instance-function fin
  1233.                                               (make-trampoline func)))))
  1234.  
  1235. (defun make-trampoline (function)
  1236.   #'(lambda (&rest args)
  1237.       (apply function args)))
  1238.  
  1239. (eval-when (eval) (compile 'make-trampoline))
  1240.  
  1241. (defmacro funcallable-instance-data-1 (instance data)
  1242.   `(svref (cadddr ,instance)
  1243.           (funcallable-instance-data-position ,data)))
  1244.  
  1245. );end of Vaxlisp (and dec vax common)
  1246.  
  1247.  
  1248. ;;;; Implementation of funcallable instances for CMU Common Lisp:
  1249. ;;;
  1250. ;;;    We represent a FIN like a closure, but the header has a distinct type
  1251. ;;; tag.  The FIN data slots are stored at the end of a fixed-length closure
  1252. ;;; (at FIN-DATA-OFFSET.)  When the function is set to a closure that has no
  1253. ;;; more than FIN-DATA-OFFSET slots, we can just replace the slots in the FIN
  1254. ;;; with the closure slots.  If the closure has too many slots, we must
  1255. ;;; indirect through a trampoline with a rest arg.  For non-closures, we just
  1256. ;;; set the function slot.
  1257. ;;;
  1258. ;;;    We can get away with this efficient and relatively simple scheme because
  1259. ;;; the compiler currently currently only references closure slots during the
  1260. ;;; initial call and on entry into the function.  So we don't have to worry
  1261. ;;; about bad things happening when the FIN is clobbered (the problem JonL
  1262. ;;; flames about somewhere...)
  1263. ;;;
  1264. ;;;    We also stick in a slot for the function name at the end, but before the
  1265. ;;; data slots.
  1266.  
  1267. #+CMU
  1268. (import 'kernel:funcallable-instance-p)
  1269.  
  1270. #+CMU
  1271. (progn
  1272.  
  1273. (eval-when (compile load eval)
  1274.   ;;; The offset of the function's name & the max number of real closure slots.
  1275.   ;;;
  1276.   (defconstant fin-name-slot 14)
  1277.   
  1278.   ;;; The offset of the data slots.
  1279.   ;;;
  1280.   (defconstant fin-data-offset 15))
  1281.  
  1282.  
  1283. ;;; ALLOCATE-FUNCALLABLE-INSTANCE-1  --  Interface
  1284. ;;;
  1285. ;;;    Allocate a funcallable instance, setting the function to an error
  1286. ;;; function and initializing the data slots to NIL.
  1287. ;;;
  1288. (defun allocate-funcallable-instance-1 ()
  1289.   (let* ((len (+ (length funcallable-instance-data) fin-data-offset))
  1290.          (res (kernel:%make-funcallable-instance
  1291.                len
  1292.                #'called-fin-without-function)))
  1293.     (dotimes (i (length funcallable-instance-data))
  1294.       (kernel:%set-funcallable-instance-info res (+ i fin-data-offset) nil))
  1295.     (kernel:%set-funcallable-instance-info res fin-name-slot nil)
  1296.     res))
  1297.  
  1298.  
  1299. ;;; FUNCALLABLE-INSTANCE-P  --  Interface
  1300. ;;;
  1301. ;;;    Return true if X is a funcallable instance.  This is an interpreter
  1302. ;;; stub; the compiler directly implements this function.
  1303. ;;;
  1304. (defun funcallable-instance-p (x) (funcallable-instance-p x))
  1305.  
  1306.  
  1307. ;;; SET-FUNCALLABLE-INSTANCE-FUNCTION  --  Interface
  1308. ;;;
  1309. ;;;    Set the function that is called when FIN is called.
  1310. ;;;
  1311. (defun set-funcallable-instance-function (fin new-value)
  1312.   (declare (type function new-value))
  1313.   (assert (funcallable-instance-p fin))
  1314.   (ecase (kernel:get-type new-value)
  1315.     (#.vm:closure-header-type
  1316.      (let ((len (- (kernel:get-closure-length new-value)
  1317.                    (1- vm:closure-info-offset))))
  1318.        (cond ((> len fin-name-slot)
  1319.               (set-funcallable-instance-function
  1320.                fin
  1321.                #'(lambda (&rest args)
  1322.                    (apply new-value args))))
  1323.              (t
  1324.               (dotimes (i fin-data-offset)
  1325.                 (kernel:%set-funcallable-instance-info
  1326.                  fin i
  1327.                  (if (>= i len)
  1328.                      nil
  1329.                      (kernel:%closure-index-ref new-value i))))
  1330.               (kernel:%set-funcallable-instance-function
  1331.                fin
  1332.                (kernel:%closure-function new-value))))))
  1333.     (#.vm:function-header-type
  1334.      (kernel:%set-funcallable-instance-function fin new-value)))
  1335.   new-value)
  1336.  
  1337.  
  1338. ;;; FUNCALLABLE-INSTANCE-NAME, SET-FUNCALLABLE-INSTANCE-NAME  --  Interface
  1339. ;;;
  1340. ;;;    Read or set the name slot in a funcallable instance.
  1341. ;;;
  1342. (defun funcallable-instance-name (fin)
  1343.   (kernel:%closure-index-ref fin fin-name-slot))
  1344. ;;;
  1345. (defun set-funcallable-instance-name (fin new-value)
  1346.   (kernel:%set-funcallable-instance-info fin fin-name-slot new-value)
  1347.   new-value)
  1348. ;;;
  1349. (defsetf funcallable-instance-name set-funcallable-instance-name)
  1350.  
  1351.  
  1352. ;;; FUNCALLABLE-INSTANCE-DATA-1  --  Interface
  1353. ;;;
  1354. ;;;    If the slot is constant, use CLOSURE-REF with the appropriate offset,
  1355. ;;; otherwise do a run-time lookup of the slot offset.
  1356. ;;;
  1357. (defmacro funcallable-instance-data-1 (fin slot)
  1358.   (if (constantp slot)
  1359.       `(sys:%primitive c:closure-ref ,fin
  1360.                        ,(+ (or (position (eval slot) funcallable-instance-data)
  1361.                                (error "Unknown slot: ~S." (eval slot)))
  1362.                            fin-data-offset))
  1363.       (ext:once-only ((n-slot slot))
  1364.         `(kernel:%closure-index-ref
  1365.           ,fin
  1366.           (+ (or (position ,n-slot funcallable-instance-data)
  1367.                  (error "Unknown slot: ~S." ,n-slot))
  1368.              fin-data-offset)))))
  1369. ;;;
  1370. (defmacro %set-funcallable-instance-data-1 (fin slot new-value)
  1371.   (ext:once-only ((n-fin fin)
  1372.                   (n-slot slot)
  1373.                   (n-val new-value))
  1374.     `(progn
  1375.        (kernel:%set-funcallable-instance-info
  1376.         ,n-fin
  1377.     ,(if (constantp slot)
  1378.          (+ (or (position (eval slot) funcallable-instance-data)
  1379.             (error "Unknown slot: ~S." (eval slot)))
  1380.         fin-data-offset)
  1381.          `(+ (or (position ,n-slot funcallable-instance-data)
  1382.              (error "Unknown slot: ~S." ,n-slot))
  1383.          fin-data-offset))
  1384.         ,n-val)
  1385.        ,n-val)))
  1386. ;;;
  1387. (defsetf funcallable-instance-data-1 %set-funcallable-instance-data-1)
  1388.                 
  1389. ); End of #+cmu progn
  1390.  
  1391.  
  1392. ;;;
  1393. ;;; Kyoto Common Lisp (KCL)
  1394. ;;;
  1395. ;;; In KCL, compiled functions and compiled closures are defined as c structs.
  1396. ;;; This means that in order to access their fields, we have to use C code!
  1397. ;;; The C code we call and the lisp interface to it is in the file kcl-low.
  1398. ;;; The lisp interface to this code implements accessors to compiled closures
  1399. ;;; and compiled functions of about the same level of abstraction as that
  1400. ;;; which is used by the other implementation dependent versions of FINs in
  1401. ;;; this file.
  1402. ;;;
  1403.  
  1404. #+(and KCL (not IBCL))
  1405. (progn
  1406.  
  1407. (defvar *funcallable-instance-marker* (list "Funcallable Instance Marker"))
  1408.  
  1409. (defconstant funcallable-instance-closure-size 15)
  1410.  
  1411. (defconstant funcallable-instance-closure-size1
  1412.   (1- funcallable-instance-closure-size))
  1413.  
  1414. (defconstant funcallable-instance-available-size
  1415.   (- funcallable-instance-closure-size1
  1416.      (length funcallable-instance-data)))
  1417.  
  1418. (defmacro funcallable-instance-marker (x)
  1419.   `(car (cclosure-env-nthcdr funcallable-instance-closure-size1 ,x)))
  1420.  
  1421. (defun allocate-funcallable-instance-1 ()
  1422.   (let ((fin (allocate-funcallable-instance-2))
  1423.         (env (make-list funcallable-instance-closure-size :initial-element nil)))
  1424.     (setf (%cclosure-env fin) env)
  1425.     #+:turbo-closure (si:turbo-closure fin)
  1426.     (setf (funcallable-instance-marker fin) *funcallable-instance-marker*)
  1427.     fin))
  1428.  
  1429. (defun allocate-funcallable-instance-2 ()
  1430.   (let ((what-a-dumb-closure-variable ()))
  1431.     #'(lambda (&rest args)
  1432.         (declare (ignore args))
  1433.         (called-fin-without-function)
  1434.         (setq what-a-dumb-closure-variable
  1435.               (dummy-function what-a-dumb-closure-variable)))))
  1436.  
  1437. (defun funcallable-instance-p (x)
  1438.   (eq *funcallable-instance-marker* (funcallable-instance-marker x)))
  1439.  
  1440. (si:define-compiler-macro funcallable-instance-p (x)
  1441.   `(eq *funcallable-instance-marker* (funcallable-instance-marker ,x)))
  1442.  
  1443. (defun set-funcallable-instance-function (fin new-value)
  1444.   (cond ((not (funcallable-instance-p fin))
  1445.          (error "~S is not a funcallable-instance" fin))
  1446.         ((not (functionp new-value))
  1447.          (error "~S is not a function." new-value))
  1448.         ((and (cclosurep new-value)
  1449.               (<= (length (%cclosure-env new-value))
  1450.                   funcallable-instance-available-size))
  1451.          (%set-cclosure fin new-value funcallable-instance-available-size))
  1452.         (t
  1453.          (set-funcallable-instance-function
  1454.            fin (make-trampoline new-value))))
  1455.   fin)
  1456.  
  1457. (defmacro funcallable-instance-data-1 (fin data &environment env)
  1458.   ;; The compiler won't expand macros before deciding on optimizations,
  1459.   ;; so we must do it here.
  1460.   (let* ((pos-form (macroexpand `(funcallable-instance-data-position ,data)
  1461.                                 env))
  1462.          (index-form (if (constantp pos-form)
  1463.                          (- funcallable-instance-closure-size
  1464.                             (eval pos-form)
  1465.                             2)
  1466.                          `(- funcallable-instance-closure-size
  1467.                              (funcallable-instance-data-position ,data)
  1468.                              2))))
  1469.     `(car (%cclosure-env-nthcdr ,index-form ,fin))))
  1470.  
  1471.  
  1472. #+turbo-closure (clines "#define TURBO_CLOSURE")
  1473.  
  1474. (clines "
  1475. static make_trampoline_internal();
  1476. static make_turbo_trampoline_internal();
  1477.  
  1478. static object
  1479. make_trampoline(function)
  1480.      object function;
  1481. {
  1482.   vs_push(MMcons(function,Cnil));
  1483. #ifdef TURBO_CLOSURE
  1484.   if(type_of(function)==t_cclosure)
  1485.     {if(function->cc.cc_turbo==NULL)turbo_closure(function);
  1486.      vs_head=make_cclosure(make_turbo_trampoline_internal,Cnil,vs_head,Cnil,NULL,0);
  1487.      return vs_pop;}
  1488. #endif
  1489.   vs_head=make_cclosure(make_trampoline_internal,Cnil,vs_head,Cnil,NULL,0);
  1490.   return vs_pop;
  1491. }
  1492.  
  1493. static
  1494. make_trampoline_internal(base0)
  1495.      object *base0;
  1496. {super_funcall_no_event(base0[0]->c.c_car);}
  1497.  
  1498. static
  1499. make_turbo_trampoline_internal(base0)
  1500.      object *base0;
  1501. { object function=base0[0]->c.c_car;
  1502.   (*function->cc.cc_self)(function->cc.cc_turbo);
  1503. }
  1504.  
  1505. ")
  1506.  
  1507. (defentry make-trampoline (object) (object make_trampoline))
  1508. )
  1509.  
  1510. #+IBCL
  1511. (progn ; From Rainy Day PCL.  
  1512.  
  1513. (defvar *funcallable-instance-marker* (list "Funcallable Instance Marker"))
  1514.  
  1515. (defconstant funcallable-instance-closure-size 15)
  1516.  
  1517. (defun allocate-funcallable-instance-1 ()
  1518.   (let ((fin (allocate-funcallable-instance-2))
  1519.     (env
  1520.       (make-list funcallable-instance-closure-size :initial-element nil)))
  1521.     (set-cclosure-env fin env)
  1522.     #+:turbo-closure (si:turbo-closure fin)
  1523.     (dotimes (i (1- funcallable-instance-closure-size)) (pop env))
  1524.     (setf (car env) *funcallable-instance-marker*)
  1525.     fin))
  1526.  
  1527. (defun allocate-funcallable-instance-2 ()
  1528.   (let ((what-a-dumb-closure-variable ()))
  1529.     #'(lambda (&rest args)
  1530.     (declare (ignore args))
  1531.     (called-fin-without-function)
  1532.     (setq what-a-dumb-closure-variable
  1533.           (dummy-function what-a-dumb-closure-variable)))))
  1534.  
  1535. (defun funcallable-instance-p (x)
  1536.   (and (cclosurep x)
  1537.        (let ((env (cclosure-env x)))
  1538.      (when (listp env)
  1539.        (dotimes (i (1- funcallable-instance-closure-size)) (pop env))
  1540.        (eq (car env) *funcallable-instance-marker*)))))
  1541.  
  1542. (defun set-funcallable-instance-function (fin new-value)
  1543.   (cond ((not (funcallable-instance-p fin))
  1544.          (error "~S is not a funcallable-instance" fin))
  1545.         ((not (functionp new-value))
  1546.          (error "~S is not a function." new-value))
  1547.         ((cclosurep new-value)
  1548.          (let* ((fin-env (cclosure-env fin))
  1549.                 (new-env (cclosure-env new-value))
  1550.                 (new-env-size (length new-env))
  1551.                 (fin-env-size (- funcallable-instance-closure-size
  1552.                                  (length funcallable-instance-data)
  1553.                  1)))
  1554.            (cond ((<= new-env-size fin-env-size)
  1555.           (do ((i 0 (+ i 1))
  1556.                (new-env-tail new-env (cdr new-env-tail))
  1557.                (fin-env-tail fin-env (cdr fin-env-tail)))
  1558.               ((= i fin-env-size))
  1559.             (setf (car fin-env-tail)
  1560.               (if (< i new-env-size)
  1561.                   (car new-env-tail)
  1562.                   nil)))          
  1563.           (set-cclosure-self fin (cclosure-self new-value))
  1564.           (set-cclosure-data fin (cclosure-data new-value))
  1565.           (set-cclosure-start fin (cclosure-start new-value))
  1566.           (set-cclosure-size fin (cclosure-size new-value)))
  1567.                  (t                 
  1568.                   (set-funcallable-instance-function
  1569.                     fin
  1570.                     (make-trampoline new-value))))))
  1571.     ((typep new-value 'compiled-function)
  1572.      ;; Write NILs into the part of the cclosure environment that is
  1573.      ;; not being used to store the funcallable-instance-data.  Then
  1574.      ;; copy over the parts of the compiled function that need to be
  1575.      ;; copied over.
  1576.      (let ((env (cclosure-env fin)))
  1577.        (dotimes (i (- funcallable-instance-closure-size
  1578.               (length funcallable-instance-data)
  1579.               1))
  1580.          (setf (car env) nil)
  1581.          (pop env)))
  1582.      (set-cclosure-self fin (cfun-self new-value))
  1583.      (set-cclosure-data fin (cfun-data new-value))
  1584.      (set-cclosure-start fin (cfun-start new-value))
  1585.      (set-cclosure-size fin (cfun-size new-value)))     
  1586.         (t
  1587.          (set-funcallable-instance-function fin
  1588.                                             (make-trampoline new-value))))
  1589.   fin)
  1590.  
  1591.  
  1592. (defun make-trampoline (function)
  1593.   #'(lambda (&rest args)
  1594.       (apply function args)))
  1595.  
  1596. ;; this replaces funcallable-instance-data-1, set-funcallable-instance-data-1
  1597. ;; and the defsetf
  1598. (defmacro funcallable-instance-data-1 (fin data &environment env)
  1599.   ;; The compiler won't expand macros before deciding on optimizations,
  1600.   ;; so we must do it here.
  1601.   (let* ((pos-form (macroexpand `(funcallable-instance-data-position ,data)
  1602.                 env))
  1603.      (index-form (if (constantp pos-form)
  1604.              (- funcallable-instance-closure-size
  1605.                 (eval pos-form)
  1606.                 2)
  1607.              `(- funcallable-instance-closure-size
  1608.                  (funcallable-instance-data-position ,data)
  1609.                  2))))
  1610.     #+:turbo-closure `(car (tc-cclosure-env-nthcdr ,index-form ,fin))
  1611.     #-:turbo-closure `(nth ,index-form (cclosure-env ,fin))))
  1612.  
  1613. )
  1614.  
  1615.  
  1616. ;;;
  1617. ;;; In H.P. Common Lisp
  1618. ;;; This code was originally written by:
  1619. ;;;    kempf@hplabs.hp.com     (James Kempf)
  1620. ;;;    dsouza@hplabs.hp.com    (Roy D'Souza)
  1621. ;;;
  1622. #+HP-HPLabs
  1623. (progn
  1624.  
  1625. (defmacro fin-closure-size ()`(prim::@* 6 prim::bytes-per-word))
  1626.  
  1627. (defmacro fin-set-mem-hword ()
  1628.   `(prim::@set-mem-hword
  1629.      (prim::@+ fin (prim::@<< 2 1))
  1630.      (prim::@+ (prim::@<< 2 8)
  1631.            (prim::@fundef-info-parms (prim::@fundef-info fundef)))))
  1632.  
  1633. (defun allocate-funcallable-instance-1()
  1634.   (let* ((fundef
  1635.        #'(lambda (&rest ignore)
  1636.            (declare (ignore ignore))
  1637.            (called-fin-without-function)))
  1638.      (static-link (vector 'lisp::*undefined* NIL NIL NIL NIL NIL))
  1639.      (fin (prim::@make-fundef (fin-closure-size))))
  1640.     (fin-set-mem-hword)
  1641.     (prim::@set-svref fin 2 fundef)
  1642.     (prim::@set-svref fin 3 static-link)
  1643.     (prim::@set-svref fin 4 0) 
  1644.     (impl::PlantclosureHook fin)
  1645.     fin))
  1646.  
  1647. (defmacro funcallable-instance-p (possible-fin)
  1648.   `(= (fin-closure-size) (prim::@header-inf ,possible-fin)))
  1649.  
  1650. (defun set-funcallable-instance-function (fin new-function)
  1651.   (cond ((not (funcallable-instance-p fin))
  1652.      (error "~S is not a funcallable instance.~%" fin))
  1653.     ((not (functionp new-function))
  1654.      (error "~S is not a function." new-function))
  1655.     (T
  1656.      (prim::@set-svref fin 2 new-function))))
  1657.  
  1658. (defmacro funcallable-instance-data-1 (fin data)
  1659.   `(prim::@svref (prim::@closure-static-link ,fin)
  1660.          (+ 2 (funcallable-instance-data-position ,data))))
  1661.  
  1662. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  1663.   `(prim::@set-svref (prim::@closure-static-link ,fin)
  1664.              (+ (funcallable-instance-data-position ,data) 2)
  1665.              ,new-value))
  1666.  
  1667. (defun funcallable-instance-name (fin)
  1668.   (prim::@svref (prim::@closure-static-link fin) 1))
  1669.  
  1670. (defsetf funcallable-instance-name set-funcallable-instance-name)
  1671.  
  1672. (defun set-funcallable-instance-name (fin new-name)
  1673.   (prim::@set-svref (prim::@closure-static-link fin) 1 new-name))
  1674.  
  1675. );end #+HP
  1676.  
  1677.  
  1678.  
  1679. ;;;
  1680. ;;; In Golden Common Lisp.
  1681. ;;; This code was originally written by:
  1682. ;;;    dan%acorn@Live-Oak.LCS.MIT.edu     (Dan Jacobs)
  1683. ;;;
  1684. ;;; GCLISP supports named structures that are specially marked as funcallable.
  1685. ;;; This allows FUNCALLABLE-INSTANCE-P to be a normal structure predicate,
  1686. ;;; and allows ALLOCATE-FUNCALLABLE-INSTANCE-1 to be a normal boa-constructor.
  1687. ;;; 
  1688. #+GCLISP
  1689. (progn
  1690.  
  1691. (defstruct (%funcallable-instance
  1692.          (:predicate funcallable-instance-p)
  1693.          (:copier nil)
  1694.          (:constructor allocate-funcallable-instance-1 ())
  1695.          (:print-function
  1696.           (lambda (struct stream depth)
  1697.         (declare (ignore depth))
  1698.         (print-object struct stream))))
  1699.   (function    #'(lambda (ignore-this &rest ignore-these-too)
  1700.             (declare (ignore ignore-this ignore-these-too))
  1701.             (called-fin-without-function))
  1702.         :type function)
  1703.   (%hidden%    'gclisp::funcallable :read-only t)
  1704.   (data        (vector nil nil) :type simple-vector :read-only t))
  1705.  
  1706. (proclaim '(inline set-funcallable-instance-function))
  1707. (defun set-funcallable-instance-function (fin new-value)
  1708.   (setf (%funcallable-instance-function fin) new-value))
  1709.  
  1710. (defmacro funcallable-instance-data-1 (fin data)
  1711.   `(svref (%funcallable-instance-data ,fin)
  1712.       (funcallable-instance-data-position ,data)))
  1713.  
  1714. )
  1715.  
  1716.  
  1717. ;;;
  1718. ;;; Explorer Common Lisp
  1719. ;;; This code was originally written by:
  1720. ;;;    Dussud%Jenner@csl.ti.com
  1721. ;;;    
  1722. #+ti
  1723. (progn
  1724.  
  1725. #+(or :ti-release-3 (and :ti-release-2 elroy))
  1726. (defmacro lexical-closure-environment (l)
  1727.   `(cdr (si:%make-pointer si:dtp-list
  1728.               (cdr (si:%make-pointer si:dtp-list ,l)))))
  1729.  
  1730. #-(or :ti-release-3 elroy)
  1731. (defmacro lexical-closure-environment (l)
  1732.   `(caar (si:%make-pointer si:dtp-list
  1733.                (cdr (si:%make-pointer si:dtp-list ,l)))))
  1734.  
  1735. (defmacro lexical-closure-function (l)
  1736.   `(car (si:%make-pointer si:dtp-list ,l)))
  1737.  
  1738.  
  1739. (defvar *funcallable-instance-marker* (list "Funcallable Instance Marker"))
  1740.  
  1741. (defconstant funcallable-instance-closure-size 15) ; NOTE: In order to avoid
  1742.                            ; hassles with the reader,
  1743. (defmacro allocate-funcallable-instance-2 ()       ; these two 15's are the
  1744.   (let ((l ()))                       ; same.  Be sure to keep
  1745.     (dotimes (i 15)                   ; them consistent.
  1746.       (push (list (gensym) nil) l))
  1747.     `(let ,l
  1748.        #'(lambda (ignore &rest ignore-them-too)
  1749.        (declare (ignore ignore ignore-them-too))
  1750.        (called-fin-without-function)
  1751.        (values . ,(mapcar #'car l))))))
  1752.  
  1753. (defun allocate-funcallable-instance-1 ()
  1754.   (let* ((new-fin (allocate-funcallable-instance-2)))
  1755.     (setf (car (nthcdr (1- funcallable-instance-closure-size)
  1756.                (lexical-closure-environment new-fin)))
  1757.       *funcallable-instance-marker*) 
  1758.     new-fin))
  1759.  
  1760. (eval-when (eval) (compile 'allocate-funcallable-instance-1))
  1761.  
  1762. (proclaim '(inline funcallable-instance-p))
  1763. (defun funcallable-instance-p (x)
  1764.   (and (typep x #+:ti-release-2 'closure
  1765.             #+:ti-release-3 'si:lexical-closure)
  1766.        (let ((env (lexical-closure-environment x)))
  1767.      (eq (nth (1- funcallable-instance-closure-size) env)
  1768.          *funcallable-instance-marker*))))
  1769.  
  1770. (defun set-funcallable-instance-function (fin new-value)
  1771.   (cond ((not (funcallable-instance-p fin))
  1772.      (error "~S is not a funcallable-instance"))
  1773.     ((not (functionp new-value))
  1774.      (error "~S is not a function."))
  1775.     ((typep new-value 'si:lexical-closure)
  1776.      (let* ((fin-env (lexical-closure-environment fin))
  1777.         (new-env (lexical-closure-environment new-value))
  1778.         (new-env-size (length new-env))
  1779.         (fin-env-size (- funcallable-instance-closure-size
  1780.                  (length funcallable-instance-data)
  1781.                  1)))
  1782.        (cond ((<= new-env-size fin-env-size)
  1783.           (do ((i 0 (+ i 1))
  1784.                (new-env-tail new-env (cdr new-env-tail))
  1785.                (fin-env-tail fin-env (cdr fin-env-tail)))
  1786.               ((= i fin-env-size))
  1787.             (setf (car fin-env-tail)
  1788.               (if (< i new-env-size)
  1789.                   (car new-env-tail)
  1790.                   nil)))          
  1791.           (setf (lexical-closure-function fin)
  1792.             (lexical-closure-function new-value)))
  1793.          (t
  1794.           (set-funcallable-instance-function
  1795.             fin
  1796.             (make-trampoline new-value))))))
  1797.     (t
  1798.      (set-funcallable-instance-function fin
  1799.                         (make-trampoline new-value)))))
  1800.  
  1801. (defun make-trampoline (function)
  1802.   (let ((tmp))
  1803.     #'(lambda (&rest args) tmp
  1804.     (apply function args))))
  1805.  
  1806. (eval-when (eval) (compile 'make-trampoline))
  1807.     
  1808. (defmacro funcallable-instance-data-1 (fin data)
  1809.   `(let ((env (lexical-closure-environment ,fin)))
  1810.      (nth (- funcallable-instance-closure-size
  1811.          (funcallable-instance-data-position ,data)
  1812.          2)
  1813.       env)))
  1814.  
  1815.  
  1816. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  1817.   `(let ((env (lexical-closure-environment ,fin)))
  1818.      (setf (car (nthcdr (- funcallable-instance-closure-size
  1819.                (funcallable-instance-data-position ,data)
  1820.                2)
  1821.             env))
  1822.        ,new-value)))
  1823.  
  1824. );end of code for TI
  1825.  
  1826.  
  1827. ;;; Implemented by Bein@pyramid -- Tue Aug 25 19:05:17 1987
  1828. ;;;
  1829. ;;; A FIN is a distinct type of object which FUNCALL,EVAL, and APPLY
  1830. ;;; recognize as functions. Both Compiled-Function-P and functionp
  1831. ;;; recognize FINs as first class functions.
  1832. ;;;
  1833. ;;; This does not work with PyrLisp versions earlier than 1.1..
  1834.  
  1835. #+pyramid
  1836. (progn
  1837.  
  1838. (defun make-trampoline (function)
  1839.     #'(lambda (&rest args) (apply function args)))
  1840.  
  1841. (defun un-initialized-fin (&rest trash)
  1842.     (declare (ignore trash))
  1843.     (called-fin-without-function))
  1844.  
  1845. (eval-when (eval)
  1846.     (compile 'make-trampoline)
  1847.     (compile 'un-initialized-fin))
  1848.  
  1849. (defun allocate-funcallable-instance-1 ()
  1850.     (let ((fin (system::alloc-funcallable-instance)))
  1851.       (system::set-fin-function fin #'un-initialized-fin)
  1852.       fin))
  1853.          
  1854. (defun funcallable-instance-p (object)
  1855.   (typep object 'lisp::funcallable-instance))
  1856.  
  1857. (clc::deftransform funcallable-instance-p trans-fin-p (object)
  1858.     `(typep ,object 'lisp::funcallable-instance))
  1859.  
  1860. (defun set-funcallable-instance-function (fin new-value)
  1861.     (or (funcallable-instance-p fin)
  1862.     (error "~S is not a funcallable-instance." fin))
  1863.     (cond ((not (functionp new-value))
  1864.        (error "~S is not a function." new-value))
  1865.       ((not (lisp::compiled-function-p new-value))
  1866.        (set-funcallable-instance-function fin
  1867.                           (make-trampoline new-value)))
  1868.       (t
  1869.        (system::set-fin-function fin new-value))))
  1870.  
  1871. (defun funcallable-instance-data-1 (fin data-name)
  1872.   (system::get-fin-data fin
  1873.             (funcallable-instance-data-position data-name)))
  1874.  
  1875. (defun set-funcallable-instance-data-1 (fin data-name value)
  1876.   (system::set-fin-data fin
  1877.             (funcallable-instance-data-position data-name)
  1878.             value))
  1879.  
  1880. (defsetf funcallable-instance-data-1 set-funcallable-instance-data-1)
  1881.  
  1882. ); End of #+pyramid
  1883.  
  1884.  
  1885. ;;;
  1886. ;;; For Coral Lisp
  1887. ;;;
  1888. #+:coral
  1889. (progn
  1890.   
  1891. (defconstant ccl::$v_istruct 22)
  1892. (defvar ccl::initial-fin-slots (make-list (length funcallable-instance-data)))
  1893. (defconstant ccl::fin-function 1)
  1894. (defconstant ccl::fin-data (+ ccl::FIN-function 1))
  1895.  
  1896. (defun allocate-funcallable-instance-1 ()
  1897.   (apply #'ccl::%gvector 
  1898.          ccl::$v_istruct
  1899.          'ccl::funcallable-instance
  1900.          #'(lambda (&rest ignore)
  1901.              (declare (ignore ignore))
  1902.          (called-fin-without-function))
  1903.          ccl::initial-fin-slots))
  1904.  
  1905. #+:ccl-1.3
  1906. (eval-when (eval compile load)
  1907.  
  1908. ;;; Make uvector-based objects (like funcallable instances) print better.
  1909. (defun print-uvector-object (obj stream &optional print-level)
  1910.   (declare (ignore print-level))
  1911.   (print-object obj stream))
  1912.  
  1913. ;;; Inform the print system about funcallable instance uvectors.
  1914. (pushnew (cons 'ccl::funcallable-instance #'print-uvector-object)
  1915.      ccl:*write-uvector-alist*
  1916.      :test #'equal)
  1917.  
  1918. )
  1919.  
  1920. (defun funcallable-instance-p (x)
  1921.   (and (eq (ccl::%type-of x) 'ccl::internal-structure)
  1922.        (eq (ccl::%uvref x 0) 'ccl::funcallable-instance)))
  1923.  
  1924. (defun set-funcallable-instance-function (fin new-value)
  1925.   (unless (funcallable-instance-p fin)
  1926.     (error "~S is not a funcallable-instance." fin))
  1927.   (unless (functionp new-value)
  1928.     (error "~S is not a function." new-value))
  1929.   (ccl::%uvset fin ccl::FIN-function new-value))
  1930.  
  1931. (defmacro funcallable-instance-data-1 (fin data-name)
  1932.   `(ccl::%uvref ,fin 
  1933.                 (+ (funcallable-instance-data-position ,data-name)
  1934.            ccl::FIN-data)))
  1935.  
  1936. (defsetf funcallable-instance-data-1 (fin data) (new-value)
  1937.   `(ccl::%uvset ,fin 
  1938.                 (+ (funcallable-instance-data-position ,data) ccl::FIN-data)
  1939.                 ,new-value))
  1940.  
  1941. ); End of #+:coral
  1942.  
  1943.  
  1944.   
  1945. ;;;; Slightly Higher-Level stuff built on the implementation-dependent stuff.
  1946. ;;;
  1947. ;;;
  1948.  
  1949. (defmacro fsc-instance-p (fin)
  1950.   `(funcallable-instance-p ,fin))
  1951.  
  1952. (defmacro fsc-instance-class (fin)
  1953.   `(wrapper-class (funcallable-instance-data-1 ,fin 'wrapper)))
  1954.  
  1955. (defmacro fsc-instance-wrapper (fin)
  1956.   `(funcallable-instance-data-1 ,fin 'wrapper))
  1957.  
  1958. (defmacro fsc-instance-slots (fin)
  1959.   `(funcallable-instance-data-1 ,fin 'slots))
  1960.  
  1961.  
  1962.  
  1963.